package service

import (
	"context"
	"dy/internal/api/store"
	"dy/internal/models"
	"dy/pkg/password"
	"dy/pkg/util"
	"errors"
)

type UserSrv interface {
	Add(ctx context.Context, param map[string]interface{}) (int, error)
	Login(ctx context.Context, param map[string]interface{}) (int, bool, error)
	GetInfo(ctx context.Context, targetUserId, userId int) (map[string]interface{}, error)
	SetRedis(ctx context.Context, key, value string) error
}

type userService struct {
	store store.Factory
}

func (u *userService) Add(ctx context.Context, param map[string]interface{}) (int, error) {
	var dyUser *models.DyUser
	err := util.StructTo(&param, &dyUser)
	if err != nil {
		return 0, err
	}
	userId, err := u.store.User().Create(ctx, dyUser)
	if err != nil {
		return 0, err
	}
	return userId, nil
}

func (u *userService) Login(ctx context.Context, param map[string]interface{}) (int, bool, error) {
	user, flag, err := u.store.User().GetByEmail(ctx, param["username"].(string))
	if err != nil || !flag {
		return 0, false, err
	}
	flag = password.EqualsPassword(param["password"].(string), user.Password)
	if err != nil || !flag {
		return 0, false, err
	}
	return user.Id, flag, nil
}

func (u *userService) GetInfo(ctx context.Context, targetUserId, userId int) (map[string]interface{}, error) {
	dyUser, flag, err := u.store.User().Get(ctx, &models.DyUser{Id: targetUserId})
	if flag == false {
		return nil, errors.New("user not exist")
	}
	if err != nil {
		return nil, err
	}

	_, followCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"user_id": dyUser.Id}, "add_time", "")
	if err != nil {
		return nil, err
	}
	_, followerCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"follow_id": dyUser.Id}, "add_time", "")
	if err != nil {
		return nil, err
	}
	_, isFollow, err := u.store.Relation().Get(ctx, &models.DyUserRelation{UserId: userId, FollowId: dyUser.Id})
	if err != nil {
		return nil, err
	}

	user := map[string]interface{}{
		"id":             dyUser.Id,
		"name":           dyUser.Name,
		"follow_count":   followCount,
		"follower_count": followerCount,
		"is_follow":      isFollow,
	}

	return user, nil
}

func (u *userService) SetRedis(ctx context.Context, key, value string) error {
	return u.store.User().SetRedis(ctx, key, value)
}

func NewUserService(s *service) UserSrv {
	return &userService{
		store: s.store,
	}
}
